﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using CloudShot.Core.Interfaces;
using CloudShot.Properties;
using CloudShot.Services;
using CloudShot.Settings;

namespace CloudShot
{
	internal partial class SettingsForm : Form
	{
		private readonly ConfigurationService _configurationService;
		private readonly CloudShotSettings _appSettings;
		private readonly List<IImageStorage> _storages;

		public IImageStorage ActiveStorage { get; private set; }

		public SettingsForm(CloudShotSettings appSettings, IEnumerable<IImageStorage> storages)
		{
			_configurationService = new ConfigurationService();
			_appSettings = appSettings;
			_storages = storages.ToList();

			InitializeComponent();
			Icon = Resources.applicationIcon;

			LoadGeneralSettings();
			LoadStoragesSettings();
		}

		private void LoadStoragesSettings()
		{
			pnlSettings.Controls.Clear();

			foreach (ISettingsUIHolder settingsUIHolder in GetSettingsUIHolders())
			{
				settingsUIHolder.LoadSettings();
				settingsUIHolder.Control.Dock = DockStyle.Fill;
				settingsUIHolder.Control.Visible = false;
				pnlSettings.Controls.Add(settingsUIHolder.Control);
			}

            cboStorages.DisplayMember = "Name";
            cboStorages.DataSource = _storages;
		}

		private void LoadGeneralSettings()
		{
			chkOpenInBrowser.Checked = _appSettings.IsOpenInBrowser;
			chkCopyUrl.Checked = _appSettings.IsCopyUrl;
			chkCopyImage.Checked = _appSettings.IsCopyImage;
			chkCopyRecentShotPath.Checked = _appSettings.IsCopyRecentShotPath;
			hkbShot.Text = _appSettings.ShotHotkey;
			hkbRecord.Text = _appSettings.RecordHotkey;
			chkNotifications.Checked = _appSettings.IsShowNotifications;
			chkStartWithWindows.Checked = _appSettings.IsStartWithComputer;
			chkEnableSounds.Checked = _appSettings.IsEnableSounds;
			chkShowActiveStorageName.Checked = _appSettings.IsShowActiveStorageName;
		}

		private void ShowActiveStorageSettings()
		{
			if (ActiveStorage == null)
				throw new NullReferenceException("ActiveStorage cannot be null");

			toolTip.SetToolTip(cboStorages, ActiveStorage.Description);
			toolTip.SetToolTip(picInfo, ActiveStorage.Description);

			foreach (ISettingsUIHolder settingsUIHolder in GetSettingsUIHolders())
			{
			    settingsUIHolder.Control.Visible = settingsUIHolder == ActiveStorage.SettingsUIHolder;
			}
		}

		private void SaveSettings()
		{
			_appSettings.IsOpenInBrowser = chkOpenInBrowser.Checked;
			_appSettings.IsCopyUrl = chkCopyUrl.Checked;
			_appSettings.IsCopyImage = chkCopyImage.Checked;
			_appSettings.IsCopyRecentShotPath = chkCopyRecentShotPath.Checked;
			_appSettings.ShotHotkey = hkbShot.Text;
			_appSettings.RecordHotkey = hkbRecord.Text;
			_appSettings.IsShowNotifications = chkNotifications.Checked;
			_appSettings.IsEnableSounds = chkEnableSounds.Checked;
			_appSettings.IsShowActiveStorageName = chkShowActiveStorageName.Checked;
			_appSettings.IsStartWithComputer = chkStartWithWindows.Checked;
			_appSettings.ImageStorageSettingsList = CreateStorageSettings();

			if (ActiveStorage != null)
				_appSettings.ActiveStorageName = ActiveStorage.Name;

			_configurationService.WriteApplicationSettings(_appSettings);
		}

		//TODO REFACTOR
		private ImageStorageSettings[] CreateStorageSettings()
		{
			var storagesSettings = new ImageStorageSettings[_storages.Count];

			for (int index = 0; index < _storages.Count; index++)
			{
				IImageStorage storage = _storages[index];
				ISettingsUIHolder uiHolder = storage.SettingsUIHolder;

				if (uiHolder != null)
					uiHolder.SaveSettings();

				storagesSettings[index] = new ImageStorageSettings
				{
					Name = storage.Name,
					CurrentImageFormat = storage.CurrentImageFormat,
					StorageSettings = storage.SettingsRepository.Settings.Select(x => new ImageStorageSettingsItem { Name = x.Key, Value = x.Value }).ToList()
				};
			}

			return storagesSettings;
		}

		private IEnumerable<ISettingsUIHolder> GetSettingsUIHolders()
		{
			return _storages.Where(x => x.SettingsUIHolder != null).Select(x => x.SettingsUIHolder);
		}

		public void SetActiveStorage(IImageStorage storage)
		{
			cboStorages.SelectedItem = storage;
		}

		#region Event Handlers

		private void OnOkClick(object sender, EventArgs e)
		{
			if (ActiveStorage == null)
			{
				MessageBox.Show("Not set storage.\nPlease select storage.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
				tabContainer.SelectTab(tabStorage);
				cboStorages.Focus();
				return;
			}

			foreach (ISettingsUIHolder holder in GetSettingsUIHolders())
			{
				if (!holder.ValidateSettings())
				{
					tabContainer.SelectTab(tabStorage);
					cboStorages.SelectedItem = holder.Storage;
					return;
				}
			}

			if (hkbShot.Text == hkbRecord.Text && !string.IsNullOrEmpty(hkbRecord.Text))
			{
				MessageBox.Show("You cannot set the same hotkey for Shot and Record.\nPlease select another hotkey for Record.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
				tabContainer.SelectTab(tabRecordVideo);
				hkbRecord.Focus();
				return;
			}

			SaveSettings();

			DialogResult = DialogResult.OK;
		}

		private void OnActiveStorageChanged(object sender, EventArgs e)
		{
			ActiveStorage = cboStorages.SelectedItem as IImageStorage;
			ShowActiveStorageSettings();
		}

		private void OnClosing(object sender, FormClosingEventArgs e)
		{
			foreach (ISettingsUIHolder holder in GetSettingsUIHolders())
			{
				holder.ClearUnsavedSettings();
			}
		}

		#endregion
	}
}